﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace BigPixels
{
    public static class ColorExtensions
    {
        public static bool IsCloseTo(this Color first, Color second, float tolerance = 0.1f)
        {
            return AreClose(first, second);
            //bool flag = true;

            //flag = (flag && AreClose(first.R, second.R, tolerance));
            //flag = (flag && AreClose(first.G, second.G, tolerance));
            //flag = (flag && AreClose(first.B, second.B, tolerance));

            //return flag && AreClose(first.A, second.A, tolerance);
        }

        public static bool AreClose(Color first, Color second)
        {
//            return Math.Abs(first.CompareTo(second)) < 1; 
            return Math.Abs(GrayscaleDifference(first, second)) < 1.0;
        }

        public static int CompareTo(this Color first, Color second)
        {
            //return 100 * (int)(
            //    1.0 - ((double)(
            //        Math.Abs(first.R - second.R) +
            //        Math.Abs(first.G - second.G) +
            //        Math.Abs(first.B - second.B)
            //    ) / (256.0 * 3))
            //);

            double diff = GrayscaleDifference(first, second);

            if (Math.Abs(diff) < 1.0)
                return 0;
            else if (diff < 1.0)
                return -1;

            return 1;
        }

        private static double GrayscaleDifference(Color first, Color second)
        {
            var firstGray = ToGray(first);
            var secondGray = ToGray(second);

            return (firstGray - secondGray) * 100.0 / 256.0;
        }

        public static double ToGray(Color colour)
        {
            return (Convert.ToDouble(colour.B) * 0.11f)
                            + (Convert.ToDouble(colour.G) * 0.59f)
                            + (Convert.ToDouble(colour.R) * 0.3f);
        }

        public static bool AreClose(float a, float b, float tolerance = 0.1f)
        {
            if (a == b)
            {
                return true;
            }
            float num = (Math.Abs(a) + Math.Abs(b) + 10f) * tolerance;
            float num2 = a - b;
            
            return -num < num2 && num > num2;
        }

		public static Color Lighten(this Color c, int percent)
		{
			int red = (int)c.R;
			int green = (int)c.G;
			int blue = (int)c.B;

			int factor = percent / 10;

			red += factor * 16;
			green += factor * 16;
			blue += factor * 16;

			red = Math.Min(255, red);
			green = Math.Min(255, green);
			blue = Math.Min(255, blue);

			return Color.FromArgb(red, green, blue);
		}

		public static Color Darken(this Color c, int percent)
		{
			int red = (int)c.R;
			int green = (int)c.G;
			int blue = (int)c.B;

			int factor = percent / 10;

			red -= factor * 16;
			green -= factor * 16;
			blue -= factor * 16;

			red = Math.Max(0, red);
			green = Math.Max(0, green);
			blue = Math.Max(0, blue);

			return Color.FromArgb(red, green, blue);
		}

		public static Color Brighten(this Color c)
		{
			int red = (int)c.R;
			int green = (int)c.G;
			int blue = (int)c.B;

			if (red > green && red > blue)
			{
				red *= 2;
			}
			else if (green > red && green > blue)
			{
				green *= 2;
			}
			else if (blue > red && blue > green)
			{
				blue *= 2;
			}

			red = Math.Min(255, red);
			green = Math.Min(255, green);
			blue = Math.Min(255, blue);

			return Color.FromArgb(red, green, blue);
		}

		public static Color Shuffle(this Color c)
		{
			return Color.FromArgb((int)c.G, (int)c.B, (int)c.R);
		}

    }
}
